#ifndef __MVT_SFIFO_H__
#define __MVT_SFIFO_H__

#include "mvdef.h"
#include "mvos/mvos_apis.h"

MVCXX_EXTERN_BEGIN

/**
 * @brief SFIFO 模块基本使用流程参考 \n
 *     ///======== 主线程 参考代码
 *        mvt_sfifo_handle_t _hdl_sfifo = {.u8_init=0};
 *        mvt_sfifo_init(&_hdl_sfifo, MAX_MSG_NUM);
 *        
 *        //分开producer和consumer线程或协程
 *        ......
 *
 *        mvt_sfifo_dispose(&_hdl_sfifo);
 *
 *     ///======== producer 线程参考代码
 *        while (xxx) {
 *            mvt_sfifo_msg_stash();
 *        }
 *     ///======== producer end
 *
 *     ///======== consumer 线程参考代码
 *        while (xxx) {
 *            mvt_sfifo_msg_pop();
 *            //消息处理
 *            ......
 *            mvt_sfifo_msg_drop();
 *        }
 *     ///======== consumer end
 */

typedef enum   _sfifo_stash_act
{
    MVT_SFIFO_STASH_NORMAL          = 0,   ///< 普通存入
    MVT_SFIFO_STASH_CONFLICT_MODIFY = 1,   ///< 冲突检查，重复则替换
    MVT_SFIFO_STASH_CONFLICT_DROP   = 2,   ///< 冲突检查，重复则丢弃新的
    MVT_SFIFO_STASH_DROP            = 3,   ///< 丢弃目标消息
}mvt_sfifo_stash_act_e;

typedef struct _sfifo_msg_node
{
    struct _sfifo_msg_node *next;          ///< 下一个消息节点（不要直接操作！）
    mv_u32_t  u32_msg_id;                  ///< 消息ID（用于冲突检查模式）
    mv_s32_t  s32_msg_len;                 ///< 消息长度
    mv_v8_t   av8_msg[1];                  ///< 消息体
}mvt_sfifo_msg_node_t;

typedef struct _sfifo_handle
{
    union {
        struct {
            mv_u8_t       u8_init;         ///<句柄初始化标志
        };
        mv_u32_t          u32_align;
    };
    mv_s32_t              s32_cur;         ///<当前缓存消息数
    mv_s32_t              s32_max;         ///<最大缓存消息数限制
    mvt_sfifo_msg_node_t *lnk;             ///<缓存消息链
    mvos_mutex_t          mutex_sfifo_lock;///<操作线程安全锁
    mvos_sem_t            sem_sfifo_msg;   ///<消息信号量
}mvt_sfifo_handle_t; ///< （不要手动修改！）

typedef struct _sfifo_stash_content
{
    union {
        struct {
            mv_u8_t u8_act;                ///< 消息存入动作[mvt_sfifo_stash_act_e]
        };
        mv_u32_t    u32_align;
    };
    mv_u32_t    u32_msg_id;                ///< 消息ID（用于冲突检查模式）
    mv_s32_t    s32_msg_len;               ///< 消息长度
    mv_v8ptr_t  pv8_msg;                   ///< 消息体
}mvt_sfifo_stash_content_t;

typedef struct _sfifo_stash_info
{
    mv_s32_t   s32_stash_cont_num;
    mvt_sfifo_stash_content_t *pstru_stash_cont;
}mvt_sfifo_stash_info_t;
/**
 * @brief 初始化sfifo句柄
 * 
 * @param [in] phdl : sfifo句柄
 * @param [in] s32_max_msg : sfifo最大消息缓存数
 * @return 初始化结果
 * - success : MV_EC_SUCCESS
 * -  failed : MV_EC_INVALID_ARGS (句柄为空) \n
 *             MV_EC_REDEF        (已被初始化) \n
 *             MV_EC_MALLOC_FAILED(锁资源申请失败)
 */
mv_s32_t mvt_sfifo_init(mvt_sfifo_handle_t *phdl, mv_s32_t s32_max_msg);
/**
 * @brief 把消息存入目标sfifo
 * 
 * @param [in] phdl : sfifo句柄
 * @param [in] p_msg : 消息体
 * @param [in] s32_msg_len : 消息长度
 * @param [in] u32_msg_id  : 消息ID（需要使用冲突检查动作时，必须为非0）
 * @param [in] u8_act      : 消息存入动作[mvt_sfifo_stash_act_e]
 * @return 操作结果
 * - success : MV_EC_SUCCESS
 * -  failed : MV_EC_INVALID_ARGS (句柄为空) \n
 *             MV_EC_NOT_INIT     (句柄未初始化) \n
 *             MV_EC_RESOURCE_LEAK(到达最大缓存数限制) \n
 *             MV_EC_MALLOC_FAILED(节点资源申请失败) \n
 *             MV_EC_IGNORE       (act=CONFLICT_DROP且触发时)
 */
mv_s32_t mvt_sfifo_msg_stash(mvt_sfifo_handle_t *phdl, mv_vptr_t p_msg, mv_s32_t s32_msg_len, mv_u32_t u32_msg_id, mv_u8_t u8_act);
/**
 * @brief 把消息组存入目标sfifo
 * 
 * @param [in] phdl : sfifo句柄
 * @param [in] p_msg : 消息体
 * @param [in] s32_msg_len : 消息长度
 * @return 操作结果
 * - success : MV_EC_SUCCESS
 * -  failed : MV_EC_INVALID_ARGS (句柄为空) \n
 *             MV_EC_NOT_INIT     (句柄未初始化) \n
 *             MV_EC_RESOURCE_LEAK(到达最大缓存数限制) \n
 *             MV_EC_MALLOC_FAILED(节点资源申请失败) \n
 * @note 支持多消息同时存入，保证顺序和连续性
 */
mv_s32_t mvt_sfifo_msg_stash_ex(mvt_sfifo_handle_t *phdl, mvt_sfifo_stash_info_t *pstru_stash_info);

/**
 * @brief 从sfifo拿出最先的消息
 * 
 * @param [in] phdl : sfifo句柄
 * @param [out] pstru_node : 取出的消息节点
 * @return 操作结果
 * - success : MV_EC_SUCCESS
 * -  failed : MV_EC_INVALID_ARGS (句柄为空) \n
 *             MV_EC_NOT_INIT     (句柄未初始化) \n
 *             MV_EC_IGNORE       (无可取消息)
 * @note: 每一个成功取出的节点，将会同时从sfifo中剥离
 * @attention: 取出的节点，在不使用时，一定要使用"mvt_sfifo_msg_drop"进行资源释放回收！
 */
mv_s32_t mvt_sfifo_msg_pop(mvt_sfifo_handle_t *phdl, mvt_sfifo_msg_node_t **pstru_node);
/**
 * @brief 从sfifo拿出最先的消息（等待模式）
 * 
 * @param phdl            [in] sfifo句柄
 * @param pstru_node     [out] 取出的消息节点
 * @param s32_timeout_ms  [in] 超时时间（ms）, <=0为一直等待
 * @return 操作结果
 * - success : MV_EC_SUCCESS
 * -  failed : MV_EC_INVALID_ARGS (句柄为空) \n
 *             MV_EC_NOT_INIT     (句柄未初始化) \n
 *             MV_EC_IGNORE       (无可取消息)
 * 
 * @note 仅信号量初始化后此接口超时时间设定才会有效，否则等同于mvt_sfifo_msg_pop
 */
mv_s32_t mvt_sfifo_msg_pop_wait(mvt_sfifo_handle_t *phdl, mvt_sfifo_msg_node_t **pstru_node, mv_s32_t s32_timeout_ms);
/**
 * @brief 从sfifo拿出匹配的消息（类消息中心用法，一般可用以msg id为引）
 * 
 * @param phdl       [in] sfifo句柄
 * @param pstru_node [out]取出的消息节点
 * @param f_check    [in] 匹配函数(MV_EC_SUCCESS为匹配成功，MV_EC_NOT_MATCH继续匹配, else中断匹配)
 * @param p_usr_data [in] 自定义参数
 * @return MV_EC_SUCCESS : 成功
 * @return MV_EC_INVALID_ARGS (句柄为空) \n
 *         MV_EC_NOT_INIT     (句柄未初始化) \n
 *         MV_EC_IGNORE       (无可取消息)
 *         else               (f_check返回非NOT MATCH的其他错误码)
 */
mv_s32_t mvt_sfifo_msg_pop_case(mvt_sfifo_handle_t *phdl, mvt_sfifo_msg_node_t **pstru_node, mv_s32_t(*f_check)(mvt_sfifo_msg_node_t *pstru_node, mv_vptr_t p_usr_data), mv_vptr_t p_usr_data);
/**
 * @brief 释放消息节点资源
 * 
 * @param [in] pstru_node : 消息节点
 * @return 操作结果
 * - success : MV_EC_SUCCESS
 * -  failed : MV_EC_INVALID_ARGS (参数为空) \n
 */
mv_s32_t mvt_sfifo_msg_drop(mvt_sfifo_msg_node_t *pstru_node);
/**
 * @brief 清空消息队列（自动释放节点资源）
 * 
 * @param [in] phdl : sfifo句柄
 * @return \ 
 */
mv_void_t mvt_sfifo_clear(mvt_sfifo_handle_t *phdl);
/**
 * @brief 销毁释放sfifo所有资源
 * 
 * @param [in] phdl : sfifo句柄
 * @return 操作结果
 * - success : MV_EC_SUCCESS
 * -  failed : MV_EC_INVALID_ARGS (句柄为空) \n
 *             MV_EC_NOT_INIT     (句柄未初始化) \n
 */
mv_s32_t mvt_sfifo_dispose(mvt_sfifo_handle_t *phdl);

MVCXX_EXTERN_END

#endif
